package com.syl.springcloud.authorization.config;

import com.syl.springcloud.authorization.bean.AuthorizationConfig;
import com.syl.springcloud.authorization.service.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.approval.JdbcApprovalStore;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

import javax.sql.DataSource;

import static com.syl.springcloud.authorization.constant.LoginConstant.BCRYPT;

/**
 * @author syl
 * @create 2018-07-26 15:14
 **/
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private AuthenticationProvider daoAuhthenticationOauthProvider;
    @Autowired
    private MyUserDetailsService dbLoginService;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private AuthorizationConfig authorizationConfig;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer){
        oauthServer
        .tokenKeyAccess("permitAll()")
        .checkTokenAccess("isAuthenticated()")
        .allowFormAuthenticationForClients();
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
        .inMemory()
        .withClient(authorizationConfig.getClientId()) // client_id
        .secret(BCRYPT+new BCryptPasswordEncoder().encode(authorizationConfig.getSecret()))//.secret(passwordEncoder.encode("8yds9#(*2-")) // client_secret
        .accessTokenValiditySeconds(authorizationConfig.getTokenValidityS())
        .scopes(getScopes()) // 允许的授权范围
        .autoApprove(authorizationConfig.isAutoApprove()) // 不需要手动给请求授权
        .authorizedGrantTypes(getGrantTypes()) // 该client允许的授权类型
        .redirectUris( // sso 登录地址需注册后sso才有效 否则无法进入授权中心
            getRedirectUris()
        )
        ;
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints){
        endpoints
        .tokenStore(tokenStore())
        .approvalStore(approvalStore())
        .authorizationCodeServices(authorizationCodeServices())
        .authenticationManager(authentication ->
                daoAuhthenticationOauthProvider.authenticate(authentication)
        )
        .userDetailsService(dbLoginService);
    }

    private String[] getScopes(){
        return authorizationConfig.getScopes().toArray(new String[]{});
    }

    private String[] getGrantTypes(){
        return authorizationConfig.getGrantTypes().toArray(new String[]{});
    }

    private String[] getRedirectUris(){
        return authorizationConfig.getRegisteredSSoLoginUri().toArray(new String[]{});
    }

    @Bean
    public ApprovalStore approvalStore() {
        return new JdbcApprovalStore(dataSource);
    }
    @Bean
    protected AuthorizationCodeServices authorizationCodeServices() {
        return new JdbcAuthorizationCodeServices(dataSource);
    }
    @Bean
    public TokenStore tokenStore() {
        return new JdbcTokenStore(dataSource);
    }

}